package com.usefullc.system.service.component.dict;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.databind.util.ClassUtil;
import com.usefullc.common.constants.SystemConstant;
import com.usefullc.system.entity.BaseEntity;
import com.usefullc.system.entity.Pager;
import com.usefullc.system.entity.WebResult;
import com.usefullc.system.service.AbstractService;
import com.usefullc.common.util.JsonUtil;
import com.usefullc.system.domain.DataDict;
import com.usefullc.system.service.DataDictService;
import com.usefullc.system.service.component.SystemConfigComponent;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.ClassUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.reflect.FieldUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;

/**
 * 字典数据，数据返回处理
 *
 * @author: Sampson
 * @date: 2022-06-19 15:31
 */
@Component
public class DictComponent extends AbstractService {


    @Autowired
    private RedisTemplate redisTemplate;

//    @Autowired
//    private ImgCodeComponent imgCodeComponent;

    @Autowired
    private SystemConfigComponent systemConfigComponent;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Autowired
    private DataDictService dataDictService;


    public WebResult dealDict(HttpServletRequest request, WebResult webResult) {
        int maxDepth = 2;
        //是否返回字典
        String showDictText = request.getParameter(SystemConstant.SHOW_DICT_TEXT);
        boolean isShow = BooleanUtils.toBoolean(showDictText);
        if (!isShow) {
            return webResult;
        }
        Object data = webResult.getData();
        if (data == null) {
            return webResult;
        }
        try {
            if (data instanceof Pager) {
                Pager pager = (Pager) data;
                List dataList = pager.getDataList();
                List<JSONObject> jsonObjects = new ArrayList<>();
                if (CollectionUtils.isNotEmpty(dataList)) {
                    for (Object obj : dataList) {
                        if (!(obj instanceof BaseEntity)) {
                            return webResult;
                        }
                        jsonObjects.add(wrapperObject(obj,maxDepth));
                    }
                }
                pager.setDataList(jsonObjects);

            } else if (data instanceof ArrayList) {
                List dataList = (List) data;
                List<JSONObject> jsonObjects = new ArrayList<>();
                if (CollectionUtils.isNotEmpty(dataList)) {
                    for (Object obj : dataList) {
                        if (!(obj instanceof BaseEntity)) {
                            return webResult;
                        }
                        jsonObjects.add(wrapperObject(obj,maxDepth));
                    }
                }
                webResult.setData(dataList);
            } else if (data instanceof BaseEntity) {
                JSONObject jsonObject = wrapperObject(data,maxDepth);
                webResult.setData(jsonObject);
            }
        } catch (Exception e) {
            logger.error("error", e);
        }
        return webResult;

    }

    private JSONObject wrapperObject(Object obj,int depth) {
        depth--;
        String json = JsonUtil.bean2Json(obj);
        JSONObject jsonObject = JsonUtil.json2Bean(json, JSONObject.class);
        if(depth <= 0){
            return jsonObject;
        }
        Field[] declaredFields = FieldUtils.getAllFields(obj.getClass());
        for (int i = 0; i < declaredFields.length; i++) {
            Field field = declaredFields[i];
            if(StringUtils.equalsIgnoreCase(field.getName(),"serialVersionUID")){
                continue;
            }
            try {
                field.setAccessible(true);
                Object fieldValue = field.get(obj);
                field.setAccessible(false);
                if (fieldValue == null) {
                    continue;
                }
                if (fieldValue instanceof BaseEntity) {  //子对象
                    JSONObject childJsonObj = wrapperObject(fieldValue,depth);
                    jsonObject.put(field.getName(),childJsonObj);
                }else if(fieldValue instanceof List){
                    List childDataList = (List) fieldValue;
                    List<JSONObject> jsonObjects = new ArrayList<>();
                    if (childDataList.size() > 0 && childDataList.get(0) instanceof BaseEntity) {
                        for (Object childObj : childDataList) {
                            JSONObject childListJsonObj = wrapperObject(childObj,depth);
                            jsonObjects.add(childListJsonObj);
                        }
                        jsonObject.put(field.getName(),jsonObjects);
                    }
                }else{
                    DictField annotation = field.getAnnotation(DictField.class);
                    if (annotation != null) {
                        String value = annotation.value();
                        //先获取父级
                        DataDict parentDataDict = dataDictService.getParentByValue(value);
                        String code = parentDataDict.getCode();
                        DataDict dataDict = dataDictService.getCodeLikeAndValue(code, fieldValue.toString());
                        jsonObject.put(field.getName() + "Dict", dataDict);
                    } else {
                        EnumField enumField = field.getAnnotation(EnumField.class);
                        if (enumField != null) {
                            Class cls = enumField.cls();
                            Object enumValue = cls.getDeclaredMethod("getByCode",Integer.class).invoke(cls,fieldValue);
                            jsonObject.put(field.getName() + "Enum", enumValue);
                        }

                    }
                    UsefullcField usefullcField = field.getAnnotation(UsefullcField.class);
                    if(usefullcField != null){
                        Class cls = usefullcField.convertType();
                        String name = cls.getName();
                        switch (name){
                            case "java.lang.String": fieldValue = String.valueOf(fieldValue);break;
                            case "java.lang.Integer": fieldValue = Integer.parseInt(fieldValue.toString());break;
                            case "java.lang.Byte": fieldValue = Byte.parseByte(fieldValue.toString());break;
                            case "java.lang.Boolean": fieldValue = Boolean.parseBoolean(fieldValue.toString());break;
                            case "java.lang.Double": fieldValue = Double.parseDouble(fieldValue.toString());break;
                            case "java.lang.Float": fieldValue = Float.parseFloat(fieldValue.toString());break;
                            case "java.lang.Long": fieldValue = Long.parseLong(fieldValue.toString());break;
                            case "java.lang.Short": fieldValue = Short.parseShort(fieldValue.toString());break;
                        }
                        jsonObject.put(field.getName() , fieldValue);
                    }
                }



            } catch (Exception e) {
                logger.error("error", e);
            }
        }
        return jsonObject;
    }


}
